/*****************************************************************************
*
* CPE439
*
* Experiment 4.
*
* File: main.c
*
* Description: RTOS-based application that:
*             
*              Blinks LED0 at 5 Hz
*              - Count the number of state transitions of LED0 and display
*                that number on the two leftmost digits on the 7-segment 
*                display
*               - The count automatically rolls over at 99
*              Blink LED2 at 10 Hz
*              - Count the number of state transitions of LED2 and display
*                that number on the two rightmost digits on the 7-segment
*                display
*               - The count automatically rolls over at 99
*
*              Blink the 7-segment display colon at a rate of approximately
*              1 Hz using the tick hook callback.
*
* Target Device: ATmega32 on STK500 development board.
* 
* Hardware Setup: PORTA -> LEDS
*                 SPI -> SSEG DISPLAY
*
* Author: Kevin Casteel, Luis Castillo
*
* Revisions: v-1.0 (4/22/11)
*            v-1.1 (4/25/11)
*			 
*
******************************************************************************/
#define F_CPU 3686400
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "hw_init.h"
#include "spi_sseg.h"

//- semaphore declaration
xSemaphoreHandle xMutex;

/*---------------------------------------------------------
* Function: main
*
* Description: Calls functions to initialize IO, creates
* tasks, and start the scheduler.
*
* return: 0 on success, non-zero value on failure.
*---------------------------------------------------------*/
int main( void )
{  	
    //- parameter declarations
    parameters_t task1, task2;
    task1.led = PIN0;
	task1.millisec = DELAY1;
	task2.led = PIN2;
	task2.millisec = DELAY2;

	vIO_init(); 
	vSSEG_init();
	
	//- create mutex semaphore
	xMutex = xSemaphoreCreateMutex();

	//- Create tasks
	xTaskCreate((pdTASK_CODE) vTaskFunction_1, (signed char *) "T1", 
				configMINIMAL_STACK_SIZE, (void *) &task1, 1, NULL );

	xTaskCreate((pdTASK_CODE) vTaskFunction_2, (signed char *) "T2", 
				configMINIMAL_STACK_SIZE, (void *) &task2, 1, NULL );

    //- kick off the scheduler
	vTaskStartScheduler();

	return 0;
}


/*---------------------------------------------------------
* Function: vTaskFunction_1
*
* Description: Function performs the task. Toggles LED
* 			   specified by the pvParameters structure at a
*			   rate also designated by the same structure.
*
* parameter: pvParameters structure that contains the led
*			 and rate for it to be toggled.
*---------------------------------------------------------*/
void vTaskFunction_1(void *pvParameters)
{
   static uint8_t count = 0;
   parameters_t *val = (parameters_t *) pvParameters;

   //- infinite loop
   for (;;)  {
      PORTA ^= _BV(val->led); //- toggle led
	  count++;                //- count led transition
	  if(count > 99)          //- roll over at count 99
	  {
	  	count = 0;
	  }
	  //- protect SPI port
	  if(xSemaphoreTake(xMutex, 0)) //- take mutex
	  {
	    //- write count to sseg display
      	SSEG_Write_left_digits(count); 
		xSemaphoreGive(xMutex);     //- give mutex		
	  }
	  vTaskDelay(val->millisec/portTICK_RATE_MS);
   }
}


/*---------------------------------------------------------
* Function: vTaskFunction_2
*
* Description: Function performs the task. Toggles LED
* 			   specified by the pvParameters structure at a
*			   rate also designated by the same structure.
*
* parameter: pvParameters structure that contains the led
*			 and rate for it to be toggled.
*---------------------------------------------------------*/
void vTaskFunction_2(void *pvParameters)
{
   static uint8_t count = 0;
   parameters_t *val = (parameters_t *) pvParameters; 

   for (;;)  {
      PORTA ^= _BV(val->led); //- toggle led
	  count++;                //- count led transition
	  if(count > 99)          //- roll over at count 99
	  {
	  	count = 0;
	  }
	  //- protect SPI port
	  if(xSemaphoreTake(xMutex, 0)) //- take mutex
	  {
	    //- write count to sseg display
      	SSEG_Write_right_digits(count);
		xSemaphoreGive(xMutex);	    //- give mutex	
	  }
	  vTaskDelay(val->millisec/portTICK_RATE_MS);
   }
}


/*---------------------------------------------------------
* Function: vApplicationTickHook
*
* Description: Function blinks the 7-segment display colon
*              at a rate of approximately 1 Hz.
*---------------------------------------------------------*/
void vApplicationTickHook(void)
{
    static uint8_t colonFlag = 0;
	static uint16_t ticks = 0;

	//- count ticks
	ticks++;
	//- at 500 ticks toggle sseg colon
	if(ticks == 500)
	{
	  //- protect SPI port
	  xSemaphoreTake(xMutex, 0); //- take mutex
	  if (colonFlag == 1) {
	    //- If ON, turn it OFF
	    SSEG_Write_Decimal_Point(BLANK);
		colonFlag = 0;
	  } else {
	    //- If OFF, turn it ON
	    SSEG_Write_Decimal_Point(COLON);
		colonFlag = 1;
	  }
	  ticks = 0;
	  xSemaphoreGive(xMutex);    //- give mutex
	}
}


